
export class Queue<T = any> {
    head: QueueItem<T>
    tail: QueueItem<T>
    size: number
    constructor() {
        this.size = 0
        this.head = this.tail = null
    }

    poll(): T {
        if(!this.size) {
            return null
        }
        
        let p = this.head
        this.head = this.head.next
        let val = p.val
        p = null
        this.size--
        return val
    }

    push(val: T) {
        if(!this.size++) {
            this.tail = this.head = new QueueItem<T>(val)
        }
        else {
            this.tail.next = new QueueItem<T>(val)
            this.tail = this.tail.next
        }
    }

    front(): T {
        return this.head.val
    }

    get empty(): boolean {
        return this.size == 0
    }
}

class QueueItem<T = any> {
    val: T
    next: QueueItem<T>

    constructor(elem: T) {
        this.val = elem
    }
}

export enum CompareState {
    larger,
    equal,
    smaller,
    none,
}

export function iteratorOnly<T>(collection: { values(): Iterator<T> }): T {
    return collection.values().next().value
}

export function iterableOnlyKey<T>(collection: { keys(): Iterator<T> }): T {
    return collection.keys().next().value
}

export function mapSetOnly<K, V>(map: Map<K, Set<V>>): V {
    return iteratorOnly(iteratorOnly(map))
}

export function addAll<T = any>(distSet: Set<T>, srcSet: Set<T>) {
    for(let src of srcSet) {
        distSet.add(src)
    }
    return distSet
} 

export function comapreSet<T>(dist: Set<T>, src: Set<T>, reverse = 0): CompareState {
    if(dist.size < src.size) {
        return comapreSet(src, dist, 1)
    }

    src.forEach((val) => {
        if(!dist.has(val))
            return CompareState.none
    })

    if(dist.size === src.size) {
        return CompareState.equal
    }
    else if(reverse) {
        return CompareState.smaller
    }
    else {
        return CompareState.larger
    }
}